package com.ywz.framework.minio;

import com.ywz.common.ResultResp;
import com.ywz.common.StringUtils;
import io.minio.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.UUID;


/**
 * 类描述 -> minio服务类
 *
 * @Author: ywz
 * @Date: 2025/02/11
 */
@Slf4j
@Component
public class MinioService {
    @Resource
    private MinioClient minioClient;
    private static final String BUCKET_PREFIX = "my-bucket";

    /**
     * 方法描述 -> 上传文件
     *
     * @param file 文件
     * @Author: ywz
     * @Date: 2025/02/11
     */
    public ResultResp uploadFile(MultipartFile file) {
        if (file == null)
            return ResultResp.error("文件为空");
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isEmpty(originalFilename))
            return ResultResp.error("文件名不能为空");
        //获取原文件的类型
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        //使用UUID重新生成文件名，防止文件名称重复造成文件覆盖
        String fileName = UUID.randomUUID() + suffix;
        try {
            // 检查存储桶是否存在，如果不存在则创建
            checkBucket();
            // 向存储桶上传文件
            minioClient.putObject(PutObjectArgs.builder().bucket(BUCKET_PREFIX).object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType()).build());
        } catch (Exception e) {
            // 处理其他潜在异常
            log.error("发生错误: " + e);
            return ResultResp.error("Minio服务异常");
        }
        return ResultResp.success(fileName);
    }

    /**
     * 方法描述 -> 下载文件
     *
     * @param fileName 文件名
     * @param resp 响应
     * @param contentType 文件类型，比如：image/png（png图片）
     * @Author: ywz
     * @Date: 2024/11/08
     */
    public ResultResp downloadFile(String fileName, String contentType, HttpServletResponse resp) {
        if (StringUtils.isEmpties(fileName, contentType))
            return ResultResp.error("文件名类型租户标识不能为空");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(BUCKET_PREFIX).object(fileName).build();
            //输入流，通过输入流读取文件内容
            bis = new BufferedInputStream(minioClient.getObject(getObjectArgs));
            //输出流，通过输出流将文件写回浏览器
            bos = new BufferedOutputStream(resp.getOutputStream());
            // 设置相应类型
            resp.setContentType(contentType);
            int i = 0;
            while ((i = bis.read()) != -1) {
                bos.write(i);
            }
            bos.flush();
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return ResultResp.error("文件下载失败");
        } finally {
            try {
                if (bos != null) bos.close();
                if (bis != null) bis.close();
            } catch (IOException e) {
                log.error("文件流关闭失败", e);
            }
        }
        return null;
    }

    /**
     * 方法描述 -> 删除文件
     *
     * @param fileName 文件名
     * @Author: ywz
     * @Date: 2024/11/08
     */
    public ResultResp deleteFile(String fileName) {
        if (StringUtils.isEmpty(fileName))
            return ResultResp.error("文件名为空");
        try {
            for (String name : fileName.split(StringUtils.SEPARATOR))
                minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_PREFIX).object(name).build());
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return ResultResp.error("文件删除失败");
        }
        return ResultResp.success("文件删除成功");
    }

    /**
     * 根据文件路径得到预览文件绝对地址
     *
     * @param bucketName 桶名
     * @param fileName 文件名
     */
    public String getPreviewFileUrl(String bucketName, String fileName) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e) {
            log.error("获取预览文件地址失败", e);
            return "";
        }
    }

    /**
     * 方法描述 -> 创建桶
     *
     * @Author: ywz
     * @Date: 2025/02/11
     */
    private void checkBucket() throws Exception {
        // 检查指定的存储桶是否存在
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(MinioService.BUCKET_PREFIX).build());
        // 如果存储桶不存在，则创建它
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(MinioService.BUCKET_PREFIX).build());
        }
    }
}
